package net.ulrice.mdls.richclient.monitor;

import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import net.ulrice.Ulrice;
import net.ulrice.mdls.services.Application;
import net.ulrice.mdls.services.Graph;
import net.ulrice.mdls.services.JmxAttribute;
import net.ulrice.module.impl.action.UActionState;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYSplineRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;

public class ApplicationRefreshTask implements Runnable {

	private Application application;
	private JMXConnector jmxConnector;
	private int x = 0;
	
	private List<XYSeries> datasets = new ArrayList<XYSeries>();
	private MonitorController monitorController;

	public ApplicationRefreshTask(final MonitorController monitorController, final Application application, final ViewCallback viewCallback) {
		try {
			this.application = application;
			this.monitorController = monitorController;
	
			for (Graph graph : application.getGraphs()) {
				viewCallback.addGraph(createChart(graph));
			}
			
	
			JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + application.getJmxHost() + ":" + application.getJmxPort() + "/jmxrmi");
			jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
			
	
			monitorController.setActionStates(new UActionState("StartMonitoring", false), new UActionState("StopMonitoring", true));
	
			Runtime.getRuntime().addShutdownHook(new Thread() {
				
				@Override
				public void run() {
					super.run();
	
					try {
						jmxConnector.close();
					} catch (IOException e) {
						Ulrice.getMessageHandler().handleException(e);
					}
				}
				
			});
		} catch(Throwable th) {
			monitorController.postException(th);
			monitorController.setActionStates(new UActionState("StartMonitoring", true), new UActionState("StopMonitoring", false));
		}
	}

	private ChartPanel createChart(Graph graph) {
        NumberAxis xAxis = new NumberAxis("X");
        xAxis.setAutoRangeIncludesZero(false);
        NumberAxis yAxis = new NumberAxis("Y");
        yAxis.setAutoRangeIncludesZero(false);
        xAxis.setTickUnit(new NumberTickUnit(1.0));

        XYSplineRenderer renderer1 = new XYSplineRenderer();
        

        XYSeriesCollection series = new XYSeriesCollection();
        
        XYPlot plot = new XYPlot(series, xAxis, yAxis, renderer1);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(4, 4, 4, 4));

        // create and return the chart panel...
        JFreeChart chart = new JFreeChart(graph.getName(), JFreeChart.DEFAULT_TITLE_FONT, plot, true);
        ChartUtilities.applyCurrentTheme(chart);
        ChartPanel chartPanel = new ChartPanel(chart, false);
        
		for (JmxAttribute attribute : graph.getAttributes()) {
	        XYSeries dataSeries = new XYSeries(attribute.getName());
	        series.addSeries(dataSeries);
	        datasets.add(dataSeries);
		}
        
        return chartPanel;
	}

	@Override
	public void run() {
		try {
			x++;
			MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection();

			int i = 0; 
			for (Graph graph : application.getGraphs()) {
				for (JmxAttribute attribute : graph.getAttributes()) {
					try {
						Object attributeValue = mbeanConn.getAttribute(new ObjectName(attribute.getObjectName()), attribute.getName());
						System.out.println(attribute.getName() + " = " + attributeValue);
						datasets.get(i).add(x, (Number)attributeValue);
						i++;
						
					} catch (IOException e) {
						monitorController.postException(e);
					} catch (MalformedObjectNameException e) {
						monitorController.postException(e);
					} catch (AttributeNotFoundException e) {
						monitorController.postException(e);
					} catch (InstanceNotFoundException e) {
						monitorController.postException(e);
					} catch (MBeanException e) {
						monitorController.postException(e);
					} catch (ReflectionException e) {
						monitorController.postException(e);
					}
				}
			}
		
		} catch (Throwable th) {			
			monitorController.postException(th);
			monitorController.setActionStates(new UActionState("StartMonitoring", true), new UActionState("StopMonitoring", false));
		}
	}
}
